"""
统一数据库连接管理器
- 支持 PostgreSQL, MySQL, Oracle, SQL Server
- 支持同步/异步模式切换
- 基于 SQLAlchemy 2.0 和 SQLModel
"""
import logging
from typing import Optional, Dict, Any

from sqlalchemy import create_engine
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, Session
from sqlmodel import SQLModel

from config.config_manager import get_database_config

logger = logging.getLogger(__name__)

class DatabaseManager:
    """数据库连接管理器"""

    def __init__(self):
        self._engine = None
        self._async_engine = None
        self._session_factory = None
        self._async_session_factory = None
        self.db_config = None

    def _get_connection_url(self, db_config: Dict[str, Any], sync_mode: bool = True) -> str:
        """根据配置构建数据库连接URL"""
        db_type = db_config.get("db_type", "postgresql").lower()
        user = db_config.get("user")
        password = db_config.get("password")
        host = db_config.get("host")
        port = db_config.get("port")
        db_name = db_config.get("database")
        driver = db_config.get("driver", "")

        url_map = {
            "postgresql": f"postgresql+{('psycopg' if sync_mode else 'asyncpg') if not driver else driver}://{user}:{password}@{host}:{port}/{db_name}",
            "mysql": f"mysql+{('mysqlclient' if sync_mode else 'aiomysql') if not driver else driver}://{user}:{password}@{host}:{port}/{db_name}",
            "oracle": f"oracle+{('cx_oracle' if sync_mode else 'asyncio_cx_oracle') if not driver else driver}://{user}:{password}@{host}:{port}/?service_name={db_name}",
            "sqlserver": f"mssql+pyodbc://{user}:{password}@{host}:{port}/{db_name}?driver=SQL+Server"
        }

        if db_type not in url_map:
            raise ValueError(f"不支持的数据库类型: {db_type}")
        
        url = url_map[db_type]
        logger.info(f"构建数据库连接URL (已脱敏): {db_type}://{user}:***@{host}:{port}/{db_name}")
        return url

    def initialize(self):
        """初始化数据库连接"""
        self.db_config = get_database_config()
        
        # 检查是否启用模拟模式
        if self.db_config.get("mock_mode", False):
            logger.info("🔧 数据库处于模拟模式，跳过真实数据库连接")
            return
            
        mode = self.db_config.get("mode", "sync")
        
        if mode == "sync":
            sync_url = self._get_connection_url(self.db_config, sync_mode=True)
            self._engine = create_engine(
                sync_url,
                pool_size=self.db_config.get("pool_size", 5),
                max_overflow=self.db_config.get("max_overflow", 10),
                pool_recycle=self.db_config.get("pool_recycle", 1800),
                pool_pre_ping=self.db_config.get("pool_pre_ping", True),
                connect_args={'timeout': self.db_config.get("connection_timeout", 10)},
                echo=self.db_config.get("echo", False)
            )
            self._session_factory = sessionmaker(autocommit=False, autoflush=False, bind=self._engine)
            logger.info("[SUCCESS] 同步数据库引擎初始化成功")
        elif mode == "async":
            async_url = self._get_connection_url(self.db_config, sync_mode=False)
            self._async_engine = create_async_engine(
                async_url,
                pool_size=self.db_config.get("pool_size", 5),
                max_overflow=self.db_config.get("max_overflow", 10),
                pool_recycle=self.db_config.get("pool_recycle", 1800),
                pool_pre_ping=self.db_config.get("pool_pre_ping", True),
                connect_args={'timeout': self.db_config.get("connection_timeout", 10)},
                echo=self.db_config.get("echo", False)
            )
            self._async_session_factory = sessionmaker(
                autocommit=False, autoflush=False, bind=self._async_engine, class_=AsyncSession
            )
            logger.info("[SUCCESS] 异步数据库引擎初始化成功")
        else:
            raise ValueError(f"无效的数据库模式: {mode}")

    def get_session(self) -> Session:
        """获取同步会话"""
        # 检查是否启用模拟模式
        if self.db_config and self.db_config.get("mock_mode", False):
            logger.info("🔧 模拟模式：返回模拟数据库会话")
            # 返回一个模拟的会话对象
            class MockSession:
                def __enter__(self):
                    return self
                def __exit__(self, exc_type, exc_val, exc_tb):
                    pass
                def exec(self, statement):
                    return []
                def execute(self, statement):
                    return []
            return MockSession()
            
        if not self._session_factory:
            raise RuntimeError("同步数据库未初始化，请检查配置 mode 是否为 'sync'")
        return self._session_factory()

    async def get_async_session(self) -> AsyncSession:
        """获取异步会话"""
        if not self._async_session_factory:
            raise RuntimeError("异步数据库未初始化，请检查配置 mode 是否为 'async'")
        return self._async_session_factory()

    def get_engine(self):
        """获取同步引擎"""
        return self._engine

    def get_async_engine(self):
        """获取异步引擎"""
        return self._async_engine

    def create_db_and_tables(self):
        """创建所有表 (仅用于开发和测试)"""
        if not self._engine:
            raise RuntimeError("同步数据库未初始化，无法创建表")
        logger.info("正在创建数据库表...")
        # 在这里导入所有SQLModel模型
        # from database import models # 示例
        SQLModel.metadata.create_all(self._engine)
        logger.info("[SUCCESS] 数据库表创建完成")


# 创建全局实例
db_manager = DatabaseManager()

# 导出便捷函数
def get_db_session():
    return db_manager.get_session()

async def get_async_db_session():
    return db_manager.get_async_session()

__all__ = ["db_manager", "get_db_session", "get_async_db_session"]
